﻿Namespace Cameras

    Public Class FirstPerson

        Private G As GraphicsDeviceManager
        Private OrigMouseState As MouseState = Nothing
        Public CameraPosition As Vector3 = New Vector3(123.3456, 39.53082, -122.0296) 'X: 123.3456 Y: 59.53082 Z: -122.0296
        Public LeftRightRot As Single = 3.15 ' 2.280798
        Public UpDownRot As Single = 0 '-0.3991596
        Private RotSpeed As Single = 0.1
        Private MoveSpeed As Single = 10

        Public Sub New(Graphics As GraphicsDeviceManager, InitialCameraPosition As Vector3)
            G = Graphics
            CameraPosition = InitialCameraPosition
        End Sub

        Public Sub Update(TimeDifference As Single, KeyState As KeyboardState, MoState As MouseState)
            Dim CurrentMouseState As MouseState = MoState
            Dim MovVec As Vector3 = New Vector3(0, 0, 0)
            If KeyState.IsKeyDown(Keys.Up) Then
                MovVec = MovVec + New Vector3(0, 0, -1)
            End If
            If KeyState.IsKeyDown(Keys.Down) Then
                MovVec = MovVec + New Vector3(0, 0, 1)
            End If
            If KeyState.IsKeyDown(Keys.Right) Then
                MovVec = MovVec + New Vector3(1, 0, 0)
            End If
            If KeyState.IsKeyDown(Keys.Left) Then
                MovVec = MovVec + New Vector3(-1, 0, 0)
            End If
            If KeyState.IsKeyDown(Keys.PageUp) Then
                MovVec = MovVec + New Vector3(0, 1, 0)
            End If
            If KeyState.IsKeyDown(Keys.PageDown) Then
                MovVec = MovVec + New Vector3(0, -1, 0)
            End If
            Call AddToCameraPosition(MovVec * TimeDifference)
            If CurrentMouseState <> OrigMouseState And CurrentMouseState.RightButton = ButtonState.Pressed Then
                Dim XDiff As Single = CurrentMouseState.X - OrigMouseState.X
                Dim YDiff As Single = CurrentMouseState.Y - OrigMouseState.Y
                LeftRightRot = LeftRightRot - RotSpeed * XDiff * TimeDifference
                UpDownRot = UpDownRot - RotSpeed * YDiff * TimeDifference
                OrigMouseState = CurrentMouseState
            Else
                OrigMouseState = CurrentMouseState
            End If
        End Sub

        Private Sub AddToCameraPosition(VectorToAdd As Vector3)
            Dim CR As Matrix = Matrix.CreateRotationX(UpDownRot) * Matrix.CreateRotationY(LeftRightRot)
            Dim RotVec As Vector3 = Vector3.Transform(VectorToAdd, CR)
            CameraPosition = CameraPosition + MoveSpeed * RotVec
        End Sub

        Public Function GetViewMatrix() As Matrix
            Dim VM As Matrix
            Dim CR As Matrix = Matrix.CreateRotationX(UpDownRot) * Matrix.CreateRotationY(LeftRightRot)
            Dim COrgTarg As Vector3 = New Vector3(0, 0, -1)
            Dim COrgUpVec As Vector3 = New Vector3(0, 1, 0)
            Dim CRotTarg As Vector3 = Vector3.Transform(COrgTarg, CR)
            Dim CFinTarg As Vector3 = CameraPosition + CRotTarg
            Dim CRotUpVec As Vector3 = Vector3.Transform(COrgUpVec, CR)
            VM = Matrix.CreateLookAt(CameraPosition, CFinTarg, CRotUpVec)
            Return VM
        End Function

        Public Function GetReflectionViewMatrix(WaterOffset As Single) As Matrix
            Dim VM As Matrix
            Dim CR As Matrix = Matrix.CreateRotationX(UpDownRot) * Matrix.CreateRotationY(LeftRightRot)
            Dim COrgTarg As Vector3 = New Vector3(0, 0, -1)
            Dim COrgUpVec As Vector3 = New Vector3(0, 1, 0)
            Dim CRotTarg As Vector3 = Vector3.Transform(COrgTarg, CR)
            Dim CFinTarg As Vector3 = CameraPosition + CRotTarg
            Dim CRotUpVec As Vector3 = Vector3.Transform(COrgUpVec, CR)
            Dim ReflectCamPos As Vector3 = CameraPosition
            ReflectCamPos.Y = -ReflectCamPos.Y + WaterOffset * 2
            Dim ReflectTarg As Vector3 = CFinTarg
            ReflectTarg.Y = -CFinTarg.Y + WaterOffset * 2
            Dim CamRight As Vector3 = Vector3.Transform(New Vector3(1, 0, 0), CR)
            Dim InvUpVec As Vector3 = Vector3.Cross(CamRight, ReflectTarg - ReflectCamPos)
            VM = Matrix.CreateLookAt(ReflectCamPos, ReflectTarg, InvUpVec)
            Return VM
        End Function

        Public Function GetProjMatrix() As Matrix
            Dim PM As Matrix
            PM = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, G.GraphicsDevice.Viewport.AspectRatio, 0.1, 2000)
            Return PM
        End Function

    End Class

End Namespace